import os
import secrets
import socket
from datetime import timedelta
import logging

basedir = os.path.abspath(os.path.dirname(__file__))
# 定义数据目录
DATA_DIR = os.path.join(basedir, 'data')

# 获取主机IP地址
def get_host_ip():
    try:
        # 尝试获取主机IP
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception:
        return "localhost"  # 如果获取失败，返回localhost

class Config:
    """基础配置"""
    # 安全配置
    SECRET_KEY = os.environ.get('SECRET_KEY') or secrets.token_hex(16)
    JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY') or secrets.token_hex(32)
    JWT_ACCESS_TOKEN_EXPIRES = timedelta(hours=1)
    JWT_REFRESH_TOKEN_EXPIRES = timedelta(days=30)
    
    # 数据库配置
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(DATA_DIR, 'app.db')
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    
    # 性能优化配置
    CACHE_TYPE = "SimpleCache"  # 简单内存缓存
    CACHE_DEFAULT_TIMEOUT = 300  # 5分钟缓存过期
    
    # Dashboard 版本号 (用于设备状态上报中的 os_version 字段)
    DASHBOARD_VERSION = os.environ.get('DASHBOARD_VERSION', '1.0.0')
    
    # Socket.IO配置
    SOCKETIO_ASYNC_MODE = 'gevent'
    SOCKETIO_PING_TIMEOUT = 30
    SOCKETIO_PING_INTERVAL = 25
    
    # 系统监控配置（优化后）
    MONITOR_INTERVAL = 60  # 系统监控间隔(秒) - 从10秒改为60秒
    STATUS_BROADCAST_INTERVAL = 120  # 状态广播间隔(秒) - 从10秒改为2分钟
    
    # 日志配置（优化后）
    LOG_TO_STDOUT = False
    LOG_LEVEL = 'WARNING'  # 从DEBUG改为WARNING，减少日志输出
    MAX_LOG_SIZE = 5 * 1024 * 1024  # 从10MB改为5MB
    LOG_BACKUP_COUNT = 3  # 从5改为3
    
    # 实验服务配置 (从MoBox Server继承)
    HOST_IP = get_host_ip()
    JUPYTER_PORT = 8080  # Jupyter服务端口 (使用8080)
    BLOCKLY_PORT = 6060 # Blockly服务端口
    
    # 新增：按课程类型区分端口
    EXPERIMENT_PORTS = {
        'default': 8080,
        'python': 8080,
        'jupyter': 8080,
        'blockly': 6060,
    }
    
    COURSE_BASE_PATH = os.path.join(os.path.expanduser("~"), "course")
    STUDENT_WORKSPACE_PATH = os.path.join(os.path.expanduser("~"), "MoboxSpace") # 学生个人工作区
    COURSE_FILES_SERVER = os.environ.get('COURSE_FILES_SERVER') or "http://example.com/course_files"
    
    # Docker相关配置 (从MoBox Server继承)
    DOCKER_COMPOSE_TEMPLATE = "templates/docker-compose.yml.j2"
    DOCKER_DATA_PATH = os.path.join(os.path.expanduser("~"), "mobox_data")
    USER_DATA_PATH = os.path.join(DOCKER_DATA_PATH, "users")
    DATA_DIR = DATA_DIR  # 将DATA_DIR也添加到配置项中
    
    # 阿里云OSS配置 (从MoBox Server继承)
    USE_OSS = os.environ.get('USE_OSS', 'False').lower() in ('true', '1', 't')
    OSS_ENDPOINT = os.environ.get('OSS_ENDPOINT') or 'https://oss-cn-beijing.aliyuncs.com'
    OSS_BUCKET_NAME = os.environ.get('OSS_BUCKET_NAME') or 'lwx-ai-couse'
    OSS_REGION = os.environ.get('OSS_REGION') or 'cn-beijing'
    OSS_ACCESS_KEY_ID = os.environ.get('OSS_ACCESS_KEY_ID') or ''
    OSS_ACCESS_KEY_SECRET = os.environ.get('OSS_ACCESS_KEY_SECRET') or ''
    
    # 设备状态上报配置
    ENABLE_DEVICE_REPORTING = True
    DEVICE_REPORT_URL = os.environ.get('DEVICE_REPORT_URL') or 'http://manage.lwxai.cn/api/admin-api/edu/teaching-tool-report/report'
    DEVICE_REPORT_AES_KEY = os.environ.get('DEVICE_REPORT_AES_KEY') or 'S+emHDyg58oLuojKxyCXIVHWpZvPPwrW'
    DEVICE_REPORT_INTERVAL = int(os.environ.get('DEVICE_REPORT_INTERVAL') or 43200)  # 12小时检查间隔，但实际只开机上报
    
    @staticmethod
    def init_app(app):
        """初始化应用程序配置"""
        # 确保数据目录存在
        if not os.path.exists(app.config['DATA_DIR']):
            os.makedirs(app.config['DATA_DIR'])

        # 确保其他必要的目录存在（跳过Docker容器内路径）
        # 初始化应用配置时创建必要目录（跳过Docker容器内路径）
        # 由于使用Docker容器内路径，不在主机上创建目录
        # os.makedirs(app.config['COURSE_BASE_PATH'], exist_ok=True)
        # os.makedirs(app.config['STUDENT_WORKSPACE_PATH'], exist_ok=True)
        os.makedirs(app.config['DOCKER_DATA_PATH'], exist_ok=True)
        os.makedirs(app.config['USER_DATA_PATH'], exist_ok=True)


class DevelopmentConfig(Config):
    """开发环境配置"""
    DEBUG = True
    
    # 开发环境数据库
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(Config.DATA_DIR, 'development.db')
    
    # 日志级别
    LOG_LEVEL = logging.DEBUG
    
    # 开发环境下允许所有来源的CORS请求
    CORS_ORIGINS = ["*"]
    
    # JWT密钥
    JWT_SECRET_KEY = 'dev-secret-key-change-in-production'
    
    # 实验服务配置 - 从参考项目学习的配置
    # 获取主机IP，用于生成URL
    HOST_IP = get_host_ip()
    
    # Jupyter服务端口
    JUPYTER_PORT = 8080
    BLOCKLY_PORT = 6060 # Blockly服务端口
    
    # 按课程类型区分端口 (可以覆盖基础配置)
    EXPERIMENT_PORTS = {
        'default': 8080,
        'python': 8080,
        'jupyter': 8080,
        'blockly': 6060,
    }
    
    # Docker服务映射端口范围
    PORT_RANGE_START = 8001
    PORT_RANGE_END = 9000
    
    # 课程文件相关配置 - 生产环境使用Docker容器内路径
    COURSE_BASE_PATH = "/home/lwx/work/course"  # Docker容器内课程路径
    STUDENT_WORKSPACE_PATH = "/home/lwx/work/course" # Docker容器内学生工作区路径
    COURSE_FILES_SERVER = "http://example.com/course_files"  # 课程文件服务器
    
    # 更频繁的状态更新（但仍然优化过）
    MONITOR_INTERVAL = 30  # 从5秒改为30秒
    STATUS_BROADCAST_INTERVAL = 60  # 从5秒改为60秒


class TestingConfig(Config):
    """测试环境配置"""
    TESTING = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
    WTF_CSRF_ENABLED = False
    SERVER_NAME = 'localhost:5001'
    # 禁用设备状态上报
    ENABLE_DEVICE_REPORTING = False


class ProductionConfig(Config):
    """生产环境配置"""
    # 优化性能的配置
    DEBUG = False
    LOG_TO_STDOUT = True
    # 降低监控频率减少资源消耗（进一步优化）
    MONITOR_INTERVAL = 120  # 从15秒改为2分钟
    STATUS_BROADCAST_INTERVAL = 300  # 从30秒改为5分钟
    # 使用文件数据库
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(Config.DATA_DIR, 'production.db')
    
    @classmethod
    def init_app(cls, app):
        """生产环境特殊配置"""
        Config.init_app(app)
        
        # 配置日志
        from logging.handlers import RotatingFileHandler
        
        if not os.path.exists('logs'):
            os.mkdir('logs')
            
        file_handler = RotatingFileHandler(
            'logs/mobox.log',
            maxBytes=cls.MAX_LOG_SIZE,
            backupCount=cls.LOG_BACKUP_COUNT
        )
        file_handler.setFormatter(logging.Formatter(
            '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
        ))
        file_handler.setLevel(logging.INFO)
        
        # 添加到应用日志记录器
        app.logger.addHandler(file_handler)
        app.logger.setLevel(logging.INFO)
        app.logger.info('MOBOX Dashboard启动')

    # 设备状态上报配置
    ENABLE_DEVICE_REPORTING = True
    DEVICE_REPORT_INTERVAL = 1800  # 生产环境30分钟上报一次


# 注册配置类
config = {
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig
} 